1 module hunt.templates.rule;
2 
3 import std.regex;
4 import std.exception;
5 import std.string;
6 
7 import hunt.templates.match;
8 
9 void template_engine_throw(string type, string message) {
10 	throw new Exception("[Template Engine exception." ~ type ~ "] " ~ message);
11 }
12 
13 enum  Type {
14 	Comment,
15 	Condition,
16 	ConditionBranch,
17 	Expression,
18 	Loop,
19 	Main,
20 	String
21 }
22 
23 enum  Delimiter {
24 	Comment,
25 	Expression,
26 	LineStatement,
27 	Statement
28 }
29 
30 enum  Statement {
31 	Condition,
32 	Include,
33 	Loop
34 }
35 
36 //the order is import
37 enum  Function {
38 	Not,
39 	And,
40 	Or,
41 	In,
42 	Equal,
43 	Greater,
44 	GreaterEqual,
45 	Less,
46 	LessEqual,
47 	Different,
48 	Callback,
49 	DivisibleBy,
50 	Even,
51 	First,
52 	Float,
53 	Int,
54 	Last,
55 	Length,
56 	Lower,
57 	Max,
58 	Min,
59 	Odd,
60 	Range,
61 	Result,
62 	Round,
63 	Sort,
64 	Upper,
65 	ReadJson,
66 	Default
67 }
68 
69 enum  Condition {
70 	ElseIf,
71 	If,
72 	Else 
73 }
74 
75 enum  Loop {
76 	ForListIn,
77 	ForMapIn
78 }
79 
80 static this()
81 {
82 	regex_map_delimiters = [
83 		Delimiter.Statement :  ("\\{\\%\\s*(.+?)\\s*\\%\\}"),
84 		Delimiter.LineStatement: ("(?:^|\\n)## *(.+?) *(?:\\n|$)"),
85 		Delimiter.Expression : ("\\{\\{\\s*(.+?)\\s*\\}\\}"),
86 		Delimiter.Comment: ("\\{#\\s*(.*?)\\s*#\\}")
87 	];
88 }
89 
90 __gshared string[Delimiter] regex_map_delimiters;
91 
92 enum string[Statement] regex_map_statement_openers = [
93 	Statement.Loop : ("for (.+)"),
94 	Statement.Condition : ("if (.+)"),
95 	Statement.Include : ("include \"(.+)\"")
96 ];
97 
98 enum string[Statement] regex_map_statement_closers = [
99 	Statement.Loop : ("endfor"),
100 	Statement.Condition : ("endif")
101 ];
102 
103 enum string[Loop] regex_map_loop = [
104 	Loop.ForListIn : ("for (\\w+) in (.+)"),
105 	Loop.ForMapIn : ("for (\\w+),\\s*(\\w+) in (.+)")
106 ];
107 
108 enum string[Condition] regex_map_condition = [
109 	Condition.If : ("if (.+)"),
110 	Condition.ElseIf : ("else if (.+)"),
111 	Condition.Else : ("else")
112 ];
113 
114 string function_regex(const string name, int number_arguments) {
115 	string pattern = name;
116 	pattern ~= "(?:\\(";
117 	for (int i = 0; i < number_arguments; i++) {
118 		if (i != 0) pattern ~= ",";
119 		pattern ~= "(.*)";
120 	}
121 	pattern ~= "\\))";
122 	if (number_arguments == 0) { // Without arguments, allow to use the callback without parenthesis
123 		pattern ~= "?";
124 	}
125 	return "\\s*" ~ pattern ~ "\\s*";
126 }
127 
128 enum string[Function] regex_map_functions = [
129 	Function.Not : "not (.+)",
130 	Function.And : "(.+) and (.+)",
131 	Function.Or : "(.+) or (.+)",
132 	Function.In : "(.+) in (.+)",
133 	Function.Equal : "(.+) == (.+)",
134 	Function.Greater : "(.+) > (.+)",
135 	Function.Less : "(.+) < (.+)",
136 	Function.GreaterEqual : "(.+) >= (.+)",
137 	Function.LessEqual : "(.+) <= (.+)",
138 	Function.Different : "(.+) != (.+)",
139 	Function.Default : function_regex("default", 2),
140 	Function.DivisibleBy : function_regex("divisibleBy", 2),
141 	Function.Even : function_regex("even", 1),
142 	Function.First : function_regex("first", 1),
143 	Function.Float : function_regex("float", 1),
144 	Function.Int : function_regex("int", 1),
145 	Function.Last : function_regex("last", 1),
146 	Function.Length : function_regex("length", 1),
147 	Function.Lower : function_regex("lower", 1),
148 	Function.Max : function_regex("max", 1),
149 	Function.Min : function_regex("min", 1),
150 	Function.Odd : function_regex("odd", 1),
151 	Function.Range : function_regex("range", 1),
152 	Function.Round : function_regex("round", 2),
153 	Function.Sort : function_regex("sort", 1),
154 	Function.Upper : function_regex("upper", 1),
155 	Function.ReadJson : "\\s*([^\\(\\)]*\\S)\\s*"
156 ];
157 
158 enum ElementNotation {
159 	Dot,
160 	Pointer
161 };